package com.lpf;

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.JavaModule;

import java.lang.instrument.Instrumentation;

/**
 * Byte Buddy 是一个开源 Java 库，其主要功能是帮助用户屏蔽字节码操作，以及复杂的 Instrumentation API。
 * Byte Buddy 提供了一套类型安全的 API 和注解，我们可以直接使用这些 API 和注解轻松实现复杂的字节码操作。另
 * 外，Byte Buddy 提供了针对 Java Agent 的额外 API，帮助开发人员在 Java Agent 场景轻松增强已有代码。
 *
 * 使用 Byte Buddy 提供的 API 拦截指定的类和方法
 */
public class PremainTestPro {

    public static void premain(String agentArgs, Instrumentation inst) {

        // 当拦截到符合条件的类时，会交给 AgentBuilder.Transformer 实现处理；
        // 当 Transformer 拦截到符合条件的方法时，会交给 TimeInterceptor 处理。

        // Byte Buddy 会根据 Transformer 指定的规则进行拦截并增强代码
        AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() {
            public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
                                                    TypeDescription typeDescription,
                                                    ClassLoader classLoader,
                                                    JavaModule module) {
                return builder
                        .method(ElementMatchers.<MethodDescription>any()) // method()指定哪些方法需要被拦截，ElementMatchers.any()表示拦截所有方法
                        .intercept(MethodDelegation.to(TimeInterceptor.class)); // intercept()指明拦截上述方法的拦截器
            }
        };

        // Byte Buddy专门有个AgentBuilder来处理Java Agent的场景
        new AgentBuilder
                .Default()
                .type(ElementMatchers.nameStartsWith("com.lpf")) // 根据包名前缀拦截类
                .transform(transformer) // 拦截到的类由transformer处理
                .installOn(inst); // 安装到 Instrumentation
    }

}
